/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = apmtest_comm.c                                     */
/*  NOTE      =                                                    */
/*  DATE      = 2016/02/04 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <sys/types.h>
#include "frcomm.h"
#include "module.h"
#include <frexp_comm.h>
#include <frct_comm.h>
#include <frreport_comm.h>

#include "conntrack.h"

#include "apmtest_comm.h"

void apmtest_free(void **pp_buffer)
{
    if (pp_buffer == NULL || *pp_buffer == NULL)
        return;

    frfree(*pp_buffer);
    *pp_buffer = NULL;
    return;
}

/*!
 * 将060101011f010107010101010101形式的十六进制字符串存储到buffer中
 *
 * \param hex_string        (十六进制字符串)
 * \param buffer            (buffer)
 * \param buffer_size  (CICS数据包)
 *
 * \return 0  失败\n
 *         1  成功
 *
 */
int apmtest_hex_string_to_bin(const char *hex_string, char *buffer, size_t buffer_size)
{
    char *dst = buffer;
    char *end = buffer + buffer_size;
    unsigned int u;

    if (buffer_size < strlen(hex_string) / 2)
        return FR_FAIL;

    while (dst < end && sscanf(hex_string, "%2x", &u) == 1)
    {
        *dst++ = u;
        hex_string += 2;
    }

    return FR_SUCC;
}

static void __frcap_node_free(Frlist_node *node)
{
    if(node == NULL || node->data==NULL)
        return;
    Apm_packet *p_st_packet = (Apm_packet *)node->data;
    if(p_st_packet->p_payload)
        frfree(p_st_packet->p_payload);
    frfree(p_st_packet);

    return;
}

static void __frl7session_free(L7_module *p_st_l7_module, L7_session *p_st_l7_session)
{
    if(p_st_l7_session == NULL)
        return;

    if(p_st_l7_session->p_username)
    {
        frfree(p_st_l7_session->p_username);
        p_st_l7_session->p_username = NULL;
    }

    if(p_st_l7_session->p_session_private )
    {
        if( p_st_l7_module && p_st_l7_module->session_destory)
        {
            p_st_l7_module->session_destory(p_st_l7_session->p_session_private);
        }
        p_st_l7_session->p_session_private = NULL;
    }

    return;
}

static void __frct_l7analyzer_free(L7_analyzer *p_st_l7_analyzer)
{
    if(p_st_l7_analyzer == NULL)
        return;

    if(p_st_l7_analyzer->p_st_session)
    {
        __frl7session_free(p_st_l7_analyzer->p_st_l7_module, p_st_l7_analyzer->p_st_session);
        apmtest_free((void **) &p_st_l7_analyzer->p_st_session);
    }

    if(p_st_l7_analyzer->p_st_transaction)
    {
        frl7trans_free(p_st_l7_analyzer->p_st_transaction);
        apmtest_free((void **) &p_st_l7_analyzer->p_st_transaction);
    }

    if(p_st_l7_analyzer->p_st_l7_module)
    {
        __sync_fetch_and_sub(&p_st_l7_analyzer->p_st_l7_module->ul_refcnt, 1);
        apmtest_free((void **) &p_st_l7_analyzer->p_st_l7_module);
    }

    memset(p_st_l7_analyzer, 0x00, sizeof(L7_analyzer));
    return;
}

/**
 * 需要自己设置
 *   p_st_conn->st_l7_analyzer.p_st_session->arr_session_id
 */
int apmtest_create_ct(Conntrack **pp_st_conn, fn_session_destory p_session_destory, char *src_ip,
                      char *dst_ip, unsigned short src_port, unsigned short dst_port)
{
    Conntrack *p_st_conn = NULL;
    if ((p_st_conn = (Conntrack *) frmalloc(sizeof(Conntrack))) == NULL)
        goto error;
    memset(p_st_conn, 0x00, sizeof(Conntrack));
    p_st_conn->flg_direct_known = FR_DIRECT_KNOWN;

    p_st_conn->st_l7_analyzer.p_st_session = (L7_session *) frmalloc(sizeof(L7_session));
    if (p_st_conn->st_l7_analyzer.p_st_session == NULL)
        goto error;
    memset(p_st_conn->st_l7_analyzer.p_st_session, 0x00, sizeof(L7_session));

    if ((p_st_conn->st_l7_analyzer.p_st_l7_module = (L7_module *) frmalloc(sizeof(L7_module))) == NULL)
        goto error;

    p_st_conn->st_l7_analyzer.p_st_l7_module->session_destory = p_session_destory;

    p_st_conn->src_ip = iptools_parse_ipaddr(src_ip);
    p_st_conn->dst_ip = iptools_parse_ipaddr(dst_ip);
    p_st_conn->src_port = src_port;
    p_st_conn->dst_port = dst_port;
    *pp_st_conn = p_st_conn;

    return FR_SUCC;
error:
    return FR_FAIL;
}

void apmtest_destroy_ct(Conntrack **pp_st_conn)
{
    if (pp_st_conn == NULL)
        return;
    Conntrack *p_st_ct = *pp_st_conn;
    if(p_st_ct == NULL)
        return;
    frlist_remove_all(&p_st_ct->lst_cap_queue, __frcap_node_free);

//    if(p_st_ct->st_masterInfo.p_st_l7_module)
//        __sync_fetch_and_sub(&p_st_ct->st_masterInfo.p_st_l7_module->ul_refcnt, 1);
    if(p_st_ct->st_masterInfo.p_lst_hdr_param)
        frexpect_free_param(&p_st_ct->st_masterInfo.p_lst_hdr_param);

    __frct_l7analyzer_free(&p_st_ct->st_l7_analyzer);
//    if(p_st_ct->p_st_timer_entry)
//    {
//        if(p_st_ct->p_st_timer_entry->p_st_event)
//        {
//            frtimer_free(p_st_ct->p_st_timer_entry->p_st_event);
//            p_st_ct->p_st_timer_entry->p_st_event = NULL;
//        }
//        frfree(p_st_ct->p_st_timer_entry);
//        p_st_ct->p_st_timer_entry = NULL;
//    }
//
//    释放lua信息
//    if(p_st_ct->st_luaInfo.p_lua_cfg)
//        frlua_config_put((Lua_cfg *)p_st_ct->st_luaInfo.p_lua_cfg);
//
//    pthread_spin_destroy(&p_st_ct->lock);
    apmtest_free((void **) pp_st_conn);

    return;

}

void list_report_node_free(Frlist_node *p_st_node)
{
    Frreport_data *p_st_report_data = NULL;
    if(p_st_node == NULL || p_st_node->data == NULL)
        return;

    p_st_report_data = (Frreport_data *) FRLIST_GET_NODE_DATA(p_st_node);
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);

    return;
}

int apmtest_create_apm_packet(Apm_packet **pp_st_packet, char *p_payload, unsigned int ui_payload_len, char *src_ip,
                              char *dst_ip, unsigned short src_port, unsigned short dst_port, struct timeval st_timestamp)
{
    Apm_packet *p_st_packet = NULL;

    if ((p_st_packet = (Apm_packet *) frmalloc(sizeof(Apm_packet))) == NULL)
        goto error;
    memset(p_st_packet, 0x00, sizeof(Apm_packet));

    if (p_payload)
        p_st_packet->p_payload = (char *) frmemdup(p_payload, ui_payload_len);
    p_st_packet->ui_payload_len = ui_payload_len;
    p_st_packet->src_ip = iptools_parse_ipaddr(src_ip);
    p_st_packet->dst_ip = iptools_parse_ipaddr(dst_ip);
    p_st_packet->src_port = src_port;
    p_st_packet->dst_port = dst_port;
    p_st_packet->st_timestamp = st_timestamp;

    *pp_st_packet = p_st_packet;

    return FR_SUCC;
error:
    return FR_FAIL;
}

void apmtest_destroy_apm_packet(Apm_packet **pp_st_packet)
{
    apmtest_free((void **) &((*pp_st_packet)->p_payload));
    apmtest_free((void **) pp_st_packet);
}
